<html><head><title>Tomcat请求处理(续)</title></head><body><div id='tit'>Tomcat请求处理(续)</div><div id='cate'>源码品读</div><div id='date'>2010年10月27日 星期三 06:03 P.M.</div><div id='page'>6</div><a id='url' href='http://hi.baidu.com/hxzon/blog/item/b827af77abc11c14b151b9ea.html'>http://hi.baidu.com/hxzon/blog/item/b827af77abc11c14b151b9ea.html</a><div id='cnt'><h3>Tomcat请求处理(续)</h3> 
<p><a href="http://zddava.javaeye.com/blog/296994">http://zddava.javaeye.com/blog/296994</a></p> 
<p>tomcat源码品读 coyote <br /> org.apache.coyote.http11.Http11Processor<br /> org.apache.coyote.http11.Http11Protocol</p> 
<h3>Tomcat请求处理(三) -- coyote请求处理</h3> 
<p>在上一篇文章文章中，Tomcat的请求处理到了JIoEndpoint$Worker#run()方法的handler.process(socket)这个调用中。 <br /> <br /> 这个handler在JIoEndpoint中是这样定义的：</p> 
<pre>protected Handler handler = null;</pre> 
<p>这个Handler是在JIoEndpoint内部定义的一个接口，它的内部只有public boolean process(Socket socket);这一个方法。 <br /> <br /> 那么这个handler到底在哪里实现的呢？ <br /> <br /> 这个还要从org.apache.coyote.http11.Http11Protocol#init()中处理的，也就是在Tomcat的初始化过程中设置的。</p> 
<pre>endpoint.setHandler(cHandler);</pre> 
<p>这个cHandler就是设置的handler，它的定义如下：</p> 
<pre>protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);</pre> 
<p>这个Http11ConnectionHandler是一个Http11Protocol的内部类，它的process()方法如下所示：</p> 
<pre>public boolean process(Socket socket) {<br />   // 获取processor<br />   Http11Processor processor = recycledProcessors.poll();<br />   try {<br />    if (processor == null) {<br />     // 如果为空创建一个<br />     processor = createProcessor();<br />    }<br /><br />    if (processor instanceof ActionHook) {<br />     // 设置Http11Processor的一个成员变量started为true<br />     ((ActionHook) processor).action(ActionCode.ACTION_START, null);<br />    }<br />    // 设置SSL支持<br />    if (proto.secure &amp;&amp; (proto.sslImplementation != null)) {<br />     processor.setSSLSupport(proto.sslImplementation.getSSLSupport(socket));<br />    } else {<br />     processor.setSSLSupport(null);<br />    }<br />    // 继续处理<br />    processor.process(socket);<br />    return false;<br /><br />   } catch (java.net.SocketException e) {<br />    Http11Protocol.log.debug(<br />      sm.getString(&quot;http11protocol.proto.socketexception.debug&quot;), e);<br />   } catch (java.io.IOException e) {<br />    Http11Protocol.log.debug(sm.getString(&quot;http11protocol.proto.ioexception.debug&quot;), e);<br />   } catch (Throwable e) {<br />    Http11Protocol.log.error(sm.getString(&quot;http11protocol.proto.error&quot;), e);<br />   } finally {<br />    if (processor instanceof ActionHook) {<br />     // 设置Http11Processor的一个成员变量started为false<br />     ((ActionHook) processor).action(ActionCode.ACTION_STOP, null);<br />    }<br />    // 回收processor<br />    recycledProcessors.offer(processor);<br />   }<br />   return false;<br />  }</pre> 
<p>首先，程序要创建一个Http11Processor对象，然后将它内部的一个标志started设为true，然后将socket对象传给Http11Processor#process()去继续请求流程。 <br /> <br /> 最后请求结束后，程序会确保started设为false，并且会回收前面使用的Http11Processor对象。 <br /> <br /> 于是，接下来请求就到了Http11Processor#process()这个方法了。</p> 
<pre>public void process(Socket socket) throws IOException {<br />  // 请求信息，request对象<br />  RequestInfo rp = request.getRequestProcessor();<br />  // 设定请求的状态为STAGE_PARSE<br />  rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);<br /><br />  // 设定远端地址<br />  remoteAddr = null;<br />  remoteHost = null;<br />  localAddr = null;<br />  localName = null;<br />  remotePort = -1;<br />  localPort = -1;<br /><br />  // IO设定<br />  this.socket = socket;<br />  // 输入<br />  inputBuffer.setInputStream(socket.getInputStream());<br />  // 输出<br />  outputBuffer.setOutputStream(socket.getOutputStream());<br /><br />  // 错误标志<br />  error = false;<br />  keepAlive = true;<br /><br />  // 保持连接的计数器<br />  int keepAliveLeft = maxKeepAliveRequests;<br />  // 超时设置<br />  int soTimeout = socket.getSoTimeout();<br />  int oldSoTimeout = soTimeout;<br /><br />  // 当前JIoEndpoint中的已经使用的Worker与总Worker的比例<br />  int threadRatio = (endpoint.getCurrentThreadsBusy() * 100) / endpoint.getMaxThreads();<br />  if (threadRatio &gt; 75) {// 如果使用中的Worker比例高于75%，只保持连接1次<br />   keepAliveLeft = 1;<br />  }<br /><br />  if (soTimeout != oldSoTimeout) {<br />   try {<br />    socket.setSoTimeout(soTimeout);<br />   } catch (Throwable t) {<br />    log.debug(sm.getString(&quot;http11processor.socket.timeout&quot;), t);<br />    error = true;<br />   }<br />  }<br />  // 是否被保持着连接<br />  boolean keptAlive = false;<br /><br />  while (started &amp;&amp; !error &amp;&amp; keepAlive) {// 循环处理请求<br /><br />   // Parsing the request header<br />   // 解析请求Header<br />   try {<br />    if (!disableUploadTimeout &amp;&amp; keptAlive) {<br />     if (keepAliveTimeout &gt; 0) {<br />      socket.setSoTimeout(keepAliveTimeout);<br />     } else if (soTimeout &gt; 0) {<br />      socket.setSoTimeout(soTimeout);<br />     }<br />    }<br />    // 读取请求行<br />    inputBuffer.parseRequestLine();<br />    // 请求开始时间<br />    request.setStartTime(System.currentTimeMillis());<br />    keptAlive = true;<br /><br />    if (!disableUploadTimeout) {<br />     socket.setSoTimeout(timeout);<br />    }<br />    // 读取Header<br />    inputBuffer.parseHeaders();<br />   } catch (IOException e) {<br />    // 设置错误标志，跳出循环<br />    error = true;<br />    break;<br />   } catch (Throwable t) {<br />    if (log.isDebugEnabled()) {<br />     log.debug(sm.getString(&quot;http11processor.header.parse&quot;), t);<br />    }<br />    // 400 - 错误的请求<br />    response.setStatus(400);<br />    error = true;<br />   }<br /><br />   rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);<br />   try {<br />    // 准备请求<br />    prepareRequest();<br />   } catch (Throwable t) {<br />    if (log.isDebugEnabled()) {<br />     log.debug(sm.getString(&quot;http11processor.request.prepare&quot;), t);<br />    }<br />    response.setStatus(400);<br />    error = true;<br />   }<br /><br />   // 设置是否请求存活<br />   if (maxKeepAliveRequests &gt; 0 &amp;&amp; --keepAliveLeft == 0)<br />    keepAlive = false;<br /><br />   if (!error) {<br />    try {<br />     rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);<br />     // adapter是org.apache.catalina.connector.CoyoteAdapter类的对象<br />     adapter.service(request, response);<br /><br />     if (keepAlive &amp;&amp; !error) {<br />      // 判断是否有异常<br />      error = response.getErrorException() != null<br />        || statusDropsConnection(response.getStatus());<br />     }<br /><br />    } catch (InterruptedIOException e) {<br />     error = true;<br />    } catch (Throwable t) {<br />     log.error(sm.getString(&quot;http11processor.request.process&quot;), t);<br />     response.setStatus(500);<br />     error = true;<br />    }<br />   }<br /><br />   // 结束请求<br />   try {<br />    rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);<br />    inputBuffer.endRequest();<br />   } catch (IOException e) {<br />    error = true;<br />   } catch (Throwable t) {<br />    log.error(sm.getString(&quot;http11processor.request.finish&quot;), t);<br />    response.setStatus(500);<br />    error = true;<br />   }<br />   try {<br />    rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);<br />    outputBuffer.endRequest();<br />   } catch (IOException e) {<br />    error = true;<br />   } catch (Throwable t) {<br />    log.error(sm.getString(&quot;http11processor.response.finish&quot;), t);<br />    error = true;<br />   }<br /><br />   if (error) {<br />    response.setStatus(500);<br />   }<br />   request.updateCounters();<br /><br />   rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);<br /><br />   inputBuffer.nextRequest();<br />   outputBuffer.nextRequest();<br /><br />  }<br /><br />  rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);<br /><br />  // 回收<br />  inputBuffer.recycle();<br />  outputBuffer.recycle();<br /><br />  sslSupport = null;<br /> }</pre> 
<p>这里面需要重点说的是adapter.service(request, response);这一句，它对请求进行了进一步处理。这里的adapter是 org.apache.catalina.connector.CoyoteAdapter类的对象，至于是哪里设定的这里就不详细介绍了，主要来看一下它的#service(org.apache.coyote.Request req, org.apache.coyote.Response res)方法。</p> 
<pre>public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {<br />  // 对Coyote Request和Response进行封装<br />  Request request = (Request) req.getNote(ADAPTER_NOTES);<br />  Response response = (Response) res.getNote(ADAPTER_NOTES);<br /><br />  if (request == null) {<br />   // 重新创建封装的Coyote Request和Response对象<br />   request = (Request) connector.createRequest();<br />   request.setCoyoteRequest(req);<br />   response = (Response) connector.createResponse();<br />   response.setCoyoteResponse(res);<br /><br />   // 互相引用<br />   request.setResponse(response);<br />   response.setRequest(request);<br /><br />   req.setNote(ADAPTER_NOTES, request);<br />   res.setNote(ADAPTER_NOTES, response);<br /><br />   req.getParameters().setQueryStringEncoding(connector.getURIEncoding());<br /><br />  }<br /><br />  if (connector.getXpoweredBy()) {<br />   response.addHeader(&quot;X-Powered-By&quot;, &quot;Servlet/2.5&quot;);<br />  }<br /><br />  boolean comet = false;<br /><br />  try {<br />   req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());<br />   if (postParseRequest(req, request, res, response)) {<br /><br />    // 调用Container继续请求<br />    connector.getContainer().getPipeline().getFirst().invoke(request, response);<br /><br />    if (request.isComet()) {<br />     if (!response.isClosed() &amp;&amp; !response.isError()) {<br />      if (request.getAvailable()) {<br />       if (event(req, res, SocketStatus.OPEN)) {<br />        comet = true;<br />        res.action(ActionCode.ACTION_COMET_BEGIN, null);<br />       }<br />      } else {<br />       comet = true;<br />       res.action(ActionCode.ACTION_COMET_BEGIN, null);<br />      }<br />     } else {<br />      request.setFilterChain(null);<br />     }<br />    }<br /><br />   }<br /><br />   if (!comet) {<br />    response.finishResponse();<br />    req.action(ActionCode.ACTION_POST_REQUEST, null);<br />   }<br /><br />  } catch (IOException e) {<br />   ;<br />  } catch (Throwable t) {<br />   log.error(sm.getString(&quot;coyoteAdapter.service&quot;), t);<br />  } finally {<br />   req.getRequestProcessor().setWorkerThreadName(null);<br />   // 回收<br />   if (!comet) {<br />    request.recycle();<br />    response.recycle();<br />   } else {<br />    request.clearEncoders();<br />    response.clearEncoders();<br />   }<br />  }<br /><br /> }</pre> 
<p>下面准备总结下之前的Tomcat请求处理过程，总结出一些宏观性的东西。</p> 
<h3>Tomcat请求处理(四) -- Request, Response, 和Pipeline</h3> 1. Request和Response 
<br /> 当处理请求的时候，Tomcat使用org.apache.coyote.Request和org.apache.coyote.Response对象来封装对Socket的数据处理，就好像它们是输入流和输出流一样。 
<br /> Request和Response是low-level的，并不是用于在开发中使用的，所以，Tomcat使用了适配器模式定义了两个类 org.apache.catalina.connector.Request和 org.apache.catalina.connector.Response来对前面的low-level对象进行封装，并且扩展了 HttpServletRequest和HttpServletResponse接口，实现了Servelt规范。 
<br /> 
<br /> 2. Pipeline和Valve(不是half-life那个) 
<br /> Tomcat有四个级别的容器，在server.xml中出现了出现过3个，Engine，Host，Context。另外一个是 Wrapper，是对Servlet，JSP或者静态资源调用的一种封装，是最后一层容器了。Tomcat使用Pipeline模式在各层容器间传递请求，将请求通过管道依次通过Engine，Host，Context和Wrapper。另外，每一个容器都可以设置一系列的Valve去对请求进行拦截，就像管道中的阀一样对请求的行为进行一些干涉。 
<h3>Tomcat请求处理(五) -- 请求在容器间的流动</h3> 请求在Tomcat中传到了CoyoteAdapter的#service()方法中后，就要准备进入Pipeline了，如#service()方法中的这句所示： 
<br /> connector.getContainer().getPipeline().getFirst().invoke(request, response); 
<br /> 
<br /> 这里的Container是Engine，然后得到它的Pipeline对象，然后得到他的第一个Valve，如果没有配置的话第一个Valve 就是Basic的了，这里就是org.apache.catalina.core.StandardEngineValve，最后调用了它的#invoke()方法，源代码如下所示： 
<pre>public final void invoke(Request request, Response response) throws IOException,<br />   ServletException {<br /><br />  // 获得Host对象<br />  Host host = request.getHost();<br />  if (host == null) {<br />   response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString(<br />     &quot;standardEngine.noHost&quot;, request.getServerName()));<br />   return;<br />  }<br /><br />  // 将请求传递给Host<br />  host.getPipeline().getFirst().invoke(request, response);<br /><br /> }</pre> 
<p>这个Valve并没做什么实质性的东西，只是将请求继续传递，当然可以定义自己的Valve实现一些特殊的行为。 <br /> 还是来继续请求的处理过程，和上边Engine的情况类似，请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法，源代码如下所示：</p> 
<pre>public final void invoke(Request request, Response response) throws IOException,<br />   ServletException {<br /><br />  // 获得Context对象<br />  Context context = request.getContext();<br />  if (context == null) {<br />   response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm<br />     .getString(&quot;standardHost.noContext&quot;));<br />   return;<br />  }<br /><br />  // 如果没有设置Loader，那么设置为context自己的ClassLoader<br />  if (context.getLoader() != null) {<br />   Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());<br />  }<br /><br />  // 将请求通过Pipeline给Context<br />  context.getPipeline().getFirst().invoke(request, response);<br /><br />  if (Globals.STRICT_SERVLET_COMPLIANCE) {<br />   request.getSession(false);<br />  }<br /><br />  // 处理错误页<br />  response.setSuspended(false);<br /><br />  Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);<br /><br />  if (t != null) {<br />   throwable(request, response, t);<br />  } else {<br />   status(request, response);<br />  }<br /><br />  // 恢复ClassLoader<br />  Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());<br /><br /> }</pre> 
<p>不出意外的，请求下边就到了org.apache.catalina.core.StandardContextValve，源代码如下：</p> 
<pre>public final void invoke(Request request, Response response) throws IOException,<br />   ServletException {<br /><br />  // 不允许请求访问META-INF和WEB-INF文件夹下的内容。<br />  MessageBytes requestPathMB = request.getRequestPathMB();<br />  if ((requestPathMB.startsWithIgnoreCase(&quot;/META-INF/&quot;, 0))<br />    || (requestPathMB.equalsIgnoreCase(&quot;/META-INF&quot;))<br />    || (requestPathMB.startsWithIgnoreCase(&quot;/WEB-INF/&quot;, 0))<br />    || (requestPathMB.equalsIgnoreCase(&quot;/WEB-INF&quot;))) {<br />   notFound(response);<br />   return;<br />  }<br /><br />  // 如果系统正在重新载入中，那么暂停请求。<br />  boolean reloaded = false;<br />  while (context.getPaused()) {<br />   reloaded = true;<br />   try {<br />    Thread.sleep(1000);<br />   } catch (InterruptedException e) {<br />    ;<br />   }<br />  }<br /><br />  // 如果正在重载，停止老的WebappClassLoader并创建一个新的<br />  if (reloaded &amp;&amp; context.getLoader() != null &amp;&amp; context.getLoader().getClassLoader() != null) {<br />   Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());<br />  }<br /><br />  // 获得Wrapper对象<br />  Wrapper wrapper = request.getWrapper();<br />  if (wrapper == null) {<br />   notFound(response);<br />   return;<br />  } else if (wrapper.isUnavailable()) {<br />   wrapper = (Wrapper) container.findChild(wrapper.getName());<br />   if (wrapper == null) {<br />    notFound(response);<br />    return;<br />   }<br />  }<br /><br />  // 获得Listener列表<br />  Object instances[] = context.getApplicationEventListeners();<br /><br />  ServletRequestEvent event = null;<br /><br />  if ((instances != null) &amp;&amp; (instances.length &gt; 0)) {<br />   event = new ServletRequestEvent(((StandardContext) container).getServletContext(),<br />     request.getRequest());<br /><br />   for (int i = 0; i &lt; instances.length; i++) {<br />    if (instances[i] == null)<br />     continue;<br />    if (!(instances[i] instanceof ServletRequestListener))<br />     continue;<br />    ServletRequestListener listener = (ServletRequestListener) instances[i];<br />    try {<br />     // 调用请求初始化事件<br />     listener.requestInitialized(event);<br />    } catch (Throwable t) {<br />     container.getLogger().error(<br />       sm.getString(&quot;standardContext.requestListener.requestInit&quot;,<br />         instances[i].getClass().getName()), t);<br />     ServletRequest sreq = request.getRequest();<br />     sreq.setAttribute(Globals.EXCEPTION_ATTR, t);<br />     return;<br />    }<br />   }<br />  }<br /><br />  // 调用Wrapper的Valve<br />  wrapper.getPipeline().getFirst().invoke(request, response);<br /><br />  if ((instances != null) &amp;&amp; (instances.length &gt; 0)) {<br />   for (int i = 0; i &lt; instances.length; i++) {<br />    if (instances[i] == null)<br />     continue;<br />    if (!(instances[i] instanceof ServletRequestListener))<br />     continue;<br />    ServletRequestListener listener = (ServletRequestListener) instances[i];<br />    try {<br />     // 调用请求结束事件<br />     listener.requestDestroyed(event);<br />    } catch (Throwable t) {<br />     container.getLogger().error(<br />       sm.getString(&quot;standardContext.requestListener.requestDestroy&quot;,<br />         instances[i].getClass().getName()), t);<br />     ServletRequest sreq = request.getRequest();<br />     sreq.setAttribute(Globals.EXCEPTION_ATTR, t);<br />    }<br />   }<br />  }<br /><br /> }</pre> 
<p>这个Valve重要的是包括了对Listener的调用，最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。</p> 
<pre>public final void invoke(Request request, Response response) throws IOException,<br />   ServletException {<br /><br />  boolean unavailable = false;<br />  Throwable throwable = null;<br /><br />  long t1 = System.currentTimeMillis();<br />  requestCount++;<br />  // 获得Wrapper所关联的对象<br />  StandardWrapper wrapper = (StandardWrapper) getContainer();<br />  // Servlet对象<br />  Servlet servlet = null;<br />  // 获得Context对象<br />  Context context = (Context) wrapper.getParent();<br /><br />  if (!context.getAvailable()) {<br />   response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm<br />     .getString(&quot;standardContext.isUnavailable&quot;));<br />   unavailable = true;<br />  }<br /><br />  if (!unavailable &amp;&amp; wrapper.isUnavailable()) {<br />   container.getLogger().info(<br />     sm.getString(&quot;standardWrapper.isUnavailable&quot;, wrapper.getName()));<br />   long available = wrapper.getAvailable();<br />   if ((available &gt; 0L) &amp;&amp; (available &lt; Long.MAX_VALUE)) {<br />    response.setDateHeader(&quot;Retry-After&quot;, available);<br />    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(<br />      &quot;standardWrapper.isUnavailable&quot;, wrapper.getName()));<br />   } else if (available == Long.MAX_VALUE) {<br />    response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(<br />      &quot;standardWrapper.notFound&quot;, wrapper.getName()));<br />   }<br />   unavailable = true;<br />  }<br /><br />  try {<br />   if (!unavailable) {<br />    // 分配一个Servelt实例<br />    servlet = wrapper.allocate();<br />   }<br />  } catch (UnavailableException e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.allocateException&quot;, wrapper.getName()), e);<br />   long available = wrapper.getAvailable();<br />   if ((available &gt; 0L) &amp;&amp; (available &lt; Long.MAX_VALUE)) {<br />    response.setDateHeader(&quot;Retry-After&quot;, available);<br />    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(<br />      &quot;standardWrapper.isUnavailable&quot;, wrapper.getName()));<br />   } else if (available == Long.MAX_VALUE) {<br />    response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(<br />      &quot;standardWrapper.notFound&quot;, wrapper.getName()));<br />   }<br />  } catch (ServletException e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.allocateException&quot;, wrapper.getName()),<br />     StandardWrapper.getRootCause(e));<br />   throwable = e;<br />   exception(request, response, e);<br />   servlet = null;<br />  } catch (Throwable e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.allocateException&quot;, wrapper.getName()), e);<br />   throwable = e;<br />   exception(request, response, e);<br />   servlet = null;<br />  }<br /><br />  boolean comet = false;<br />  if (servlet instanceof CometProcessor<br />    &amp;&amp; request.getAttribute(&quot;org.apache.tomcat.comet.support&quot;) == Boolean.TRUE) {<br />   comet = true;<br />   request.setComet(true);<br />  }<br /><br />  // 告知Request已经收到<br />  try {<br />   response.sendAcknowledgement();<br />  } catch (IOException e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   container.getLogger().warn(<br />     sm.getString(&quot;standardWrapper.acknowledgeException&quot;, wrapper.getName()), e);<br />   throwable = e;<br />   exception(request, response, e);<br />  } catch (Throwable e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.acknowledgeException&quot;, wrapper.getName()), e);<br />   throwable = e;<br />   exception(request, response, e);<br />   servlet = null;<br />  }<br />  MessageBytes requestPathMB = null;<br />  if (request != null) {<br />   requestPathMB = request.getRequestPathMB();<br />  }<br />  <br />  request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,<br />    ApplicationFilterFactory.REQUEST_INTEGER);<br />  request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);<br />  // 创建FilterChain<br />  ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();<br />  ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);<br /><br />  request.setComet(false);<br /><br />  try {<br />   // web.xml中的&lt;jsp-file&gt;标签<br />   String jspFile = wrapper.getJspFile();<br />   if (jspFile != null)<br />    request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);<br />   else<br />    request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   <br />   // 调用Filter<br />   if ((servlet != null) &amp;&amp; (filterChain != null)) {<br />    if (context.getSwallowOutput()) {<br />     try {<br />      SystemLogHandler.startCapture();<br />      if (comet) {<br />       filterChain.doFilterEvent(request.getEvent());<br />       request.setComet(true);<br />      } else {<br />       filterChain.doFilter(request.getRequest(), response.getResponse());<br />      }<br />     } finally {<br />      String log = SystemLogHandler.stopCapture();<br />      if (log != null &amp;&amp; log.length() &gt; 0) {<br />       context.getLogger().info(log);<br />      }<br />     }<br />    } else {<br />     if (comet) {<br />      request.setComet(true);<br />      filterChain.doFilterEvent(request.getEvent());<br />     } else {<br />      filterChain.doFilter(request.getRequest(), response.getResponse());<br />     }<br />    }<br /><br />   }<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />  } catch (ClientAbortException e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   throwable = e;<br />   exception(request, response, e);<br />  } catch (IOException e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.serviceException&quot;, wrapper.getName()), e);<br />   throwable = e;<br />   exception(request, response, e);<br />  } catch (UnavailableException e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.serviceException&quot;, wrapper.getName()), e);<br /><br />   wrapper.unavailable(e);<br />   long available = wrapper.getAvailable();<br />   if ((available &gt; 0L) &amp;&amp; (available &lt; Long.MAX_VALUE)) {<br />    response.setDateHeader(&quot;Retry-After&quot;, available);<br />    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(<br />      &quot;standardWrapper.isUnavailable&quot;, wrapper.getName()));<br />   } else if (available == Long.MAX_VALUE) {<br />    response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(<br />      &quot;standardWrapper.notFound&quot;, wrapper.getName()));<br />   }<br /><br />  } catch (ServletException e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   Throwable rootCause = StandardWrapper.getRootCause(e);<br />   if (!(rootCause instanceof ClientAbortException)) {<br />    container.getLogger().error(<br />      sm.getString(&quot;standardWrapper.serviceException&quot;, wrapper.getName()),<br />      rootCause);<br />   }<br />   throwable = e;<br />   exception(request, response, e);<br />  } catch (Throwable e) {<br />   request.removeAttribute(Globals.JSP_FILE_ATTR);<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.serviceException&quot;, wrapper.getName()), e);<br />   throwable = e;<br />   exception(request, response, e);<br />  }<br /><br />  if (filterChain != null) {<br />   if (request.isComet()) {<br />    filterChain.reuse();<br />   } else {<br />    filterChain.release();<br />   }<br />  }<br /><br />  // 释放Servlet对象<br />  try {<br />   if (servlet != null) {<br />    wrapper.deallocate(servlet);<br />   }<br />  } catch (Throwable e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.deallocateException&quot;, wrapper.getName()), e);<br />   if (throwable == null) {<br />    throwable = e;<br />    exception(request, response, e);<br />   }<br />  }<br /><br />  try {<br />   if ((servlet != null) &amp;&amp; (wrapper.getAvailable() == Long.MAX_VALUE)) {<br />    wrapper.unload();<br />   }<br />  } catch (Throwable e) {<br />   container.getLogger().error(<br />     sm.getString(&quot;standardWrapper.unloadException&quot;, wrapper.getName()), e);<br />   if (throwable == null) {<br />    throwable = e;<br />    exception(request, response, e);<br />   }<br />  }<br />  long t2 = System.currentTimeMillis();<br /><br />  long time = t2 - t1;<br />  processingTime += time;<br />  if (time &gt; maxTime)<br />   maxTime = time;<br />  if (time &lt; minTime)<br />   minTime = time;<br /><br /> }</pre> 
<p>这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());)，具体的还要进入方法内部去仔细看一下。comet方式以后再详细看。</p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p> 
<p> </p></div></body></html>